const path = require('path');
const { spawn } = require('child_process');
const chokidar = require('chokidar');
const _ = require('lodash');

// 执行一次后，开始监听，持续编译
exceBuildNpm(() => {
  // 开启监听
  console.log('[BUILD COMPONENT] 首次编译完毕，开启监听');
  const debounceBuild = asyncDebounce(exceBuildNpm, 500);
  const codePattern = path.resolve(__dirname, 'src/**/**');
  const codeWatcher = chokidar.watch(codePattern);
  const lowcodeSettersPattern = path.resolve(__dirname, 'lowcode/**/**');
  const settersWatcher = chokidar.watch(lowcodeSettersPattern);
  ['add', 'change', 'unlink'].forEach((item) => {
    codeWatcher.on(item, async () => { await debounceBuild(); });
    settersWatcher.on(item, async () => { await debounceBuild(); });
  });
});

function exceBuildNpm(endback) {
  console.log('\n[BUILD COMPONENT] 执行编译 开始');
  const child = spawn('node', [
    './node_modules/@alib/build-scripts/bin/build-scripts.js',
    'build',
    '--config',
    './build.lowcode.js'
  ], { cwd: __dirname });
  child.stdout.pipe(process.stdout);
  child.on('close', () => {
    console.log('\n[BUILD COMPONENT] 执行编译 结束');
    endback && endback();
  });
}

function asyncDebounce(func, wait) {
  const debounced = _.debounce(async (resolve, reject, bindSelf, args) => {
    try {
      const result = await func.bind(bindSelf)(...args);
      resolve(result);
    } catch (error) {
      reject(error);
    }
  }, wait);
  function returnFunc(...args) {
    return new Promise((resolve, reject) => {
      debounced(resolve, reject, this, args);
    });
  }
  return returnFunc;
}

// 清理缓存的组件文件名（清理后会重新编译）
const clearComponents = ['button']; // ['button', 'image', 'paragraph', 'setters-view'];
const lowcodePath = path.resolve(__dirname, 'lowcode');
clearComponents.forEach((fold) => {
  const cleanSpawn = spawn('rm', ['-rf', `./${fold}`], {
    cwd: lowcodePath,
  });
  cleanSpawn.on('close', () => {
    console.log(`清理干净 /lowcode/${fold}`);
  });
});